﻿using System;
using System.Collections.Generic;
using Alone.GameObjects;
using Alone.GameObjects.Enemy;
using Microsoft.Xna.Framework;

namespace Alone.EnemyStates
{

    /// <summary>
    /// Class AttackingState, Enemies attack player if in this state.
    /// </summary>
	class AttackingState : EnemyState, IEnemyState
	{
		float attackSpeed = 7f;
		Matrix rotationMatrix;
		Vector3 movementVelocity;

        /// <summary>
        /// Initializes a new instance of the <see cref="AttackingState"/> class.
        /// </summary>
		public AttackingState()
			: base() { }

        /// <summary>
        /// Does the AI for this state.
        /// </summary>
        /// <param name="enemy">The enemy.</param>
        /// <param name="enemies">The enemies.</param>
        /// <param name="players">The players.</param>
		public override void doAI(Enemy enemy, List<Enemy> enemies, List<BasePlayer> players)
		{
			BasePlayer player = players[0];
			float distance = float.MaxValue;

			if (enemy.AnimationController.AnimationClip.Name.Equals("Bite1"))
			    enemy.AnimationController.CrossFade(enemy.SkinnedModel.AnimationClips["Walk"], TimeSpan.FromSeconds(0.2));

			enemy.AnimationController.Speed = 2f; // Sets the speed of the animation
			movementVelocity = new Vector3(0,0,attackSpeed); // Run when attacking!

			foreach (BasePlayer p in players) // Check whitch player is closest (Whitch one to attack)
			{
				float tempDist = Vector3.Distance(enemy.Position, p.Position);
				if (tempDist < distance)
				{
					distance = tempDist;
					player = p;
				}
			}

			rotationMatrix = Matrix.CreateRotationY(enemy.Rotation.Y);
			movementVelocity = Vector3.Transform(movementVelocity, rotationMatrix);

			enemy.Position += movementVelocity;

            //Keep the enemy on the heightmap
			enemy.Position.X = MathHelper.Clamp(enemy.Position.X, -3400f, 3400f);
			enemy.Position.Z = MathHelper.Clamp(enemy.Position.Z, -3400f, 3400f);
            enemy.Rotation.Y = TurnToFace(enemy.Position, player.Position, enemy.Rotation.Y, 1f);
		}

        /// <summary>
        /// Evaluates the specified enemy.
        /// </summary>
        /// <param name="enemy">The enemy.</param>
        /// <param name="enemies">The enemies.</param>
        /// <param name="player">The player.</param>
        /// <returns>A fuzzy value between 0..1</returns>
		public override float evaluate(Enemy enemy, List<Enemy> enemies, BasePlayer player)
		{
			float fuzzyValue = 0;

			fuzzyValue += isNearPlayer(enemy.Position, player.Position);

			foreach (Enemy friend in enemies)
			{
				if (enemy != friend)
				{
					if (isNearFriend(enemy.Position, friend.Position) > 0f)
					{
						// If a friend is near a player, it is more likely to attack.
						fuzzyValue += isNearPlayer(friend.Position, player.Position);
					}
				}
			}

			if (fuzzyValue > 1)
				fuzzyValue = 1;

			// If enemy is too close to player, killingState is more suitable than this state.
			fuzzyValue -= isVeryNearPlayer(enemy.Position, player.Position);

			return fuzzyValue;
		}
	}
}
